package com.endava.dao;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.endava.model.Employee;
import com.endava.model.Login;
import com.endava.util.HibernateUtil;

public class UsersDaoImpl implements UsersDao {

	private Session session;
	private SessionFactory factory;
	private final static Logger LOGGER = Logger.getLogger("Logger for UsersDaoImpl");

	public UsersDaoImpl() {
		factory = HibernateUtil.getSessionFactory();
	}

	@Override
	public Login getUserFromDb(String username, String password) {
		try {
			session = factory.openSession();
			session.beginTransaction();

			Query query = (Query) session.createQuery(SELECT_BY_CREDENTIALS);
			query.setParameter("username", username);
			query.setParameter("password", password);
			Login login = (Login) query.uniqueResult();

			session.getTransaction().commit();
			LOGGER.info("" + login);
			return login;

		} catch (HibernateException e) {
			LOGGER.info("Caught at getUserFromDb: " + e);
		} finally {
			session.close();
		}

		return null;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Employee> getAllEmployees() {
		try {
			session = factory.openSession();
			session.beginTransaction();

			List<Employee> employees = session.createQuery(SELECT_ALL_EMPLOYEES).list();

			session.getTransaction().commit();
			return employees;
		} catch (HibernateException e) {
			LOGGER.info("Caught at getAllEmployees: " + e);
		} finally {
			session.close();
		}
		return new ArrayList<Employee>(null);
	}

	@SuppressWarnings("rawtypes")
	@Override
	public Employee getUserData(String username) {
		try {
			session = factory.openSession();
			session.beginTransaction();
			Employee employee = new Employee();

			Query query = session.createQuery(SELECT_USER_DETAILS).setParameter("username", username);
			for (Iterator iterator = query.iterate(); iterator.hasNext();) {
				Object[] obj = (Object[]) iterator.next();
				employee.setFirstName((String) obj[0]);
				employee.setLastName((String) obj[1]);
				employee.setDepartment((String) obj[2]);
				employee.setSalary((double) obj[3]);
			}

			session.getTransaction().commit();
			return employee;

		} catch (HibernateException e) {
			LOGGER.info("Caught at getUserData: " + e);
		} finally {
			session.close();
		}

		return null;
	}

	@Override
	public Employee deleteEmployeeById(int id) {
		try {
			session = factory.openSession();
			session.beginTransaction();

			Employee employee = (Employee) session.load(Employee.class, id);
			session.delete(employee);
			session.getTransaction().commit();

			return employee;

		} catch (HibernateException e) {
			LOGGER.info("Caught at deleteEmployeeById: " + e);
		} finally {
			session.close();
		}

		return null;
	}

	@Override
	public Employee getEmployeeById(int id) {
		try {
			session = factory.openSession();
			session.beginTransaction();

			Employee employee = (Employee) session.createQuery(SELECT_BY_ID).setParameter("id", id).uniqueResult();
			session.getTransaction().commit();

			return employee;

		} catch (HibernateException e) {
			LOGGER.info("Caught at getEmployeeById: " + e);
		} finally {
			session.close();
		}

		return null;
	}

	@Override
	public Employee updateEmployeeData(int id, String department, double salary) {
		try {
			session = factory.openSession();

			Employee employee = (Employee) session.createQuery(SELECT_BY_ID).setParameter("id", id).uniqueResult();
			employee.setDepartment(department);
			employee.setSalary(salary);
			
			session.beginTransaction();
			session.update(employee);
			session.getTransaction().commit();
			
			LOGGER.info("UPDATED:  " + employee);
			return employee;

		} catch (HibernateException e) {
			LOGGER.info("Caught at updateEmployeeData: " + e);
			if (session.getTransaction() != null) {
				session.getTransaction().rollback();
			}
		} finally {
			session.close();
		}

		return null;
	}

}
